package com.enmonster.result;

import java.lang.reflect.*;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author wuxi
 * @create 2019/4/10 上午11:58
 */
public class Result {

    public Object getResult(Type resultType,ResultSet res,ConcurrentHashMap<String,String> resultMap) throws Exception{
        if (resultType instanceof TypeVariable) {
            return resultVariable((TypeVariable)resultType,res,resultMap);
        } else if (resultType instanceof ParameterizedType) {
            //解析ParameterizedType类型 : , 比如Map<K, V>, List<V>
            return resultList((ParameterizedType)resultType,res,resultMap);
        } else {
            //如果为普通的Class类型就直接返回 string, log, Integer
            return resultObject(resultType,res,resultMap);
        }
    }


    private  List resultList(ParameterizedType resultType,ResultSet res,ConcurrentHashMap<String,String> resultMap) throws Exception{
        Type modelType = resultType.getActualTypeArguments()[0];
        Class objClass = typeToClass(modelType);
        List result = new ArrayList();
        return  (List)resultCommons(objClass,res,resultMap,result);
    }

    private Object resultVariable(TypeVariable resultType,ResultSet res,ConcurrentHashMap<String,String> resultMap)throws Exception{
        Class objClass = typeToClass(resultType);
        return resultCommons(objClass,res,resultMap,null);
    }

    private Object resultObject(Type type,ResultSet res,ConcurrentHashMap<String,String> resultMap)throws Exception{
        Class objClass = typeToClass(type);
        return resultCommons(objClass,res,resultMap,null);
    }


    public Object resultCommons(Class objClass ,ResultSet res,ConcurrentHashMap<String,String> resultMap,List list) throws Exception{
        while (res.next()){
            Object obj = objClass.newInstance();
            Field[] declaredFields = objClass.getDeclaredFields();
            for (Field field : declaredFields) {
                String fieldName = field.getName();
                Object fieldValue = null;
                if(resultMap.size()>0 && resultMap.containsKey(fieldName)){
                    fieldValue = res.getObject(resultMap.get(fieldName));
                }else{
                    fieldValue = res.getObject(fieldName);
                }

                // 设置允许私有访问
                field.setAccessible(true);
                field.set(obj, fieldValue);
            }
            if(list != null){
                list.add(obj);
            }else{
                return obj;
            }
        }

        if(list.size()>0){
            return list;
        }
        return null;
    }

    public  Class<?> typeToClass(Type src) {
        Class<?> result = null;
        if (src instanceof Class) {
            result = (Class)src;
        } else if (src instanceof ParameterizedType) {
            result = (Class)((ParameterizedType)src).getRawType();
        } else if (src instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType)src).getGenericComponentType();
            if (componentType instanceof Class) {
                result = Array.newInstance((Class)componentType, 0).getClass();
            } else {
                Class<?> componentClass = typeToClass(componentType);
                result = Array.newInstance(componentClass, 0).getClass();
            }
        }

        if (result == null) {
            result = Object.class;
        }

        return result;
    }
}
